namespace FreeSwitch.EventSocket
{

	#region enum ChannelState

	public enum ChannelState
	{
		New, // Channel is newly created 
		Init, // Channel has been initilized
		Routing, // Channel is looking for a dialplan
		SoftExecute, // Channel is in a passive transmit state
		Execute, // Channel is executing it's dialplan 
		ExchangeMedia, // Channel is exchanging media
		Park,
		ConsumeMedia, // Channel is consuming media
		Hibernate, // Channel is in a sleep state
		Reset,
		Hangup, // Channel is flagged for hangup and ready to end
		Done, // Channel is ready to be destroyed and out of the state machine
		Unknown
	}

	#endregion

	public class ChannelInfo
	{
		private string _hostName = string.Empty;
		private int _readCodecRate;
		private int _stateNumber;
		private int _writeCodecRate;

		/// <summary>
		/// Initializes a new instance of the <see cref="ChannelInfo"/> class.
		/// </summary>
		public ChannelInfo()
		{
			Protocol = string.Empty;
			UserName = string.Empty;
			ProfileName = string.Empty;
		}

		/// <summary>
		/// Coded used to read information from the channel.
		/// Example: L16
		/// </summary>
		public string ReadCodecName { get; set; }

		/// <summary>
		/// Bitrate of the read coded that is used.
		/// Example: 8000
		/// </summary>
		public int ReadCodecRate
		{
			get { return _readCodecRate; }
			set { _readCodecRate = value; }
		}

		/// <summary>
		/// Codec used for writing to the channel.
		/// Example: L16
		/// </summary>
		public string WriteCodecName { get; set; }

		/// <summary>
		/// Bitrate of the codec.
		/// Example: 8000
		/// </summary>
		public int WriteCodecRate
		{
			get { return _writeCodecRate; }
			set { _writeCodecRate = value; }
		}

		/// <summary>
		/// State that the channel is in. Check ChannelState enum for more information.
		/// </summary>
		public ChannelState State { get; set; }

		/// <summary>
		/// Number of the state (from the enum in FreeSwitch)
		/// </summary>
		public int StateNumber
		{
			get { return _stateNumber; }
			set { _stateNumber = value; }
		}

		/// <summary>
		/// Name of the channel.
		/// </summary>
		/// <example>sofia/mydomain.com/1234@conference.freeswitch.org</example>
		/// <seealso cref="ChannelInfo.Protocol"/>
		/// <seealso cref="ProfileName"/>
		/// <seealso cref="UserName"/>
		/// <seealso cref="HostName"/>
		public string Name
		{
			get { return Protocol + "/" + ProfileName + "/" + UserName + "@" + _hostName; }
			set
			{
				string[] bits = value.Split('/');
				if (bits.Length != 3)
					return;

				Protocol = bits[0];
				ProfileName = bits[1];
				string[] userParts = bits[2].Split('@');
				if (userParts.Length == 2)
				{
					UserName = userParts[0];
					HostName = userParts[1];
				}
				else
					UserName = bits[2];
			}
		}

		/// <summary>
		/// ProfileName for the dial plan/sip.
		/// </summary>
		public string ProfileName { get; set; }

		/// <summary>
		/// Extension / User name for the channel
		/// </summary>
		public string UserName { get; set; }

		/// <summary>
		/// Where the extension/user is calling from.
		/// </summary>
		public string HostName
		{
			get { return _hostName; }
			set
			{
				if (value == null)
				{
					_hostName = string.Empty;
					return;
				}

				int pos = value.IndexOf(':');
				_hostName = pos == -1 ? value : value.Substring(0, pos);
			}
		}

		/// <summary>
		/// Protocol used for communication.
		/// "sofia" = sip.
		/// </summary>
		public string Protocol { get; private set; }

		public bool Parse(string name, string value)
		{
			switch (name)
			{
				case "channel-state":
					State = StateFromString(value);
					break;
				case "channel-state-number":
					int.TryParse(value, out _stateNumber);
					break;
				case "channel-name":
					Name = value;
					break;
				case "channel-read-codec-name":
					ReadCodecName = value;
					break;
				case "channel-read-codec-rate":
					int.TryParse(value, out _readCodecRate);
					break;
				case "channel-write-codec-name":
					WriteCodecName = value;
					break;
				case "channel-write-codec-rate":
					int.TryParse(value, out _writeCodecRate);
					break;
				default:
					return false;
			}
			return true;
		}

		public static ChannelState StateFromString(string state)
		{
			switch (state)
			{
				case "CS_NEW":
					return ChannelState.New;
				case "CS_INIT":
					return ChannelState.Init;
				case "CS_ROUTING":
					return ChannelState.Routing;
				case "CS_SOFT_EXECUTE":
					return ChannelState.SoftExecute;
				case "CS_EXECUTE":
					return ChannelState.Execute;
				case "CS_EXCHANGE_MEDIA":
					return ChannelState.ExchangeMedia;
				case "CS_PARK":
					return ChannelState.Park;
				case "CS_CONSUME_MEDIA":
					return ChannelState.ConsumeMedia;
				case "CS_HIBERNATE":
					return ChannelState.Hibernate;
				case "CS_HANGUP":
					return ChannelState.Hangup;
				case "CS_DONE":
					return ChannelState.Done;
				case "CS_RESET":
					return ChannelState.Reset;
				default:
					return ChannelState.Unknown;
			}
		}

		public static string StateToString(ChannelState state)
		{
			string stateStr = state.ToString();
			string temp = "CS_" + char.ToUpper(stateStr[0]);
			for (int i = 1; i < stateStr.Length; i++)
			{
				if (char.IsUpper(stateStr[i]))
					temp += stateStr[i] + "_";
				else
					temp += char.ToUpper(stateStr[i]);
			}

			return temp;
		}

		public override string ToString()
		{
			return UserName + "@" + _hostName + ": " + State;
		}
	}
}